home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Online / hsc / source / ugly / args_set.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  20.3 KB  |  829 lines

  1. /*
  2.  * This source code is part of hsc, a html-preprocessor,
  3.  * Copyright (C) 1993-1997  Thomas Aglassinger
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20. /*
  21.  * ugly/args_set.c
  22.  *
  23.  * ugly set arguments handling functions
  24.  *
  25.  * Copyright (C) 1994,95,96  Thomas Aglassinger
  26.  *
  27.  * This program is free software; you can redistribute it and/or modify
  28.  * it under the terms of the GNU General Public License as published by
  29.  * the Free Software Foundation; either version 2 of the License, or
  30.  * (at your option) any later version.
  31.  *
  32.  * This program is distributed in the hope that it will be useful,
  33.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  34.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  35.  * GNU General Public License for more details.
  36.  *
  37.  * You should have received a copy of the GNU General Public License
  38.  * along with this program; if not, write to the Free Software
  39.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  40.  *
  41.  * updated: 27-Sep-1997
  42.  * created:  3-Jul-1994
  43.  *
  44.  *===================================================================
  45.  * TODO:
  46.  * - support ARG_LONG_RANGE
  47.  * - support ARG_INV_SWITCH (set switch value to FALSE if NOxxx found)
  48.  * - or better: support ARG_TOGGLE (set to YES/NO)
  49.  *
  50.  */
  51.  
  52. /*
  53.  * includes
  54.  */
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <stdarg.h>
  58. #include <string.h>
  59. #include <ctype.h>
  60.  
  61. #include "utypes.h"
  62. #include "ufile.h"
  63. #include "umemory.h"
  64. #include "ustring.h"
  65. #include "dllist.h"
  66.  
  67. #define NOEXTERN_UGLY_UARGS_H
  68. #include "uargs.h"
  69.  
  70. #if 0
  71. #undef DA
  72. #define DA(x) x
  73. #endif
  74.  
  75. /*
  76.  * global export vars
  77.  *
  78.  * TODO: why the heck should this be global, if it is declared static?
  79.  */
  80. static int arg_error_num = -1;  /* error number */
  81. static STRPTR arg_error_arg = NULL;     /* argument causing error */
  82. static STRPTR arg_error_hfs = NULL;     /* error string returned by handle function */
  83.  
  84. /*
  85.  * result string for _strargerr()
  86.  */
  87. #define SIZE_ARGERRSTR 60
  88. static STRARR argerrstr[SIZE_ARGERRSTR];
  89.  
  90. /*
  91.  * local global vars
  92.  */
  93. static BOOL no_argerr = TRUE;   /* error flags for _set_args() */
  94. static BOOL any_argerr = FALSE;
  95. static int argidx = -1;         /* index in _argv[] currently examing */
  96.  
  97. /*
  98.  * compare_arginfo
  99.  *   ( called by _set_args() )
  100.  *
  101.  */
  102. static int compare_arginfo(APTR cmp_data, APTR list_data)
  103. {
  104.     struct arginfo *ai = (struct arginfo *) list_data;
  105.     STRPTR lst_arg = strclone(ai->ai_id);       /* TODO: possible enforcer hit */
  106.     STRPTR cmp_arg = ((struct arginfo *) cmp_data)->ai_id;      /* TODO: possible enforcer hit */
  107.     BOOL eq = FALSE;
  108.     char lastch;
  109.  
  110.     if (lst_arg && cmp_arg)
  111.     {
  112.         STRPTR nxt_arg = strtok(lst_arg, "=");
  113.  
  114.         while (nxt_arg && (eq == FALSE))
  115.         {
  116.             if (ai->ai_flags & ARG_CASESENS)
  117.             {
  118.                 eq = (strncmp(nxt_arg, cmp_arg, strlen(nxt_arg)) == 0);
  119.             }
  120.             else
  121.             {
  122.                 eq = (upstrncmp(nxt_arg, cmp_arg, strlen(nxt_arg)) == 0);
  123.             }
  124.  
  125. #if 0
  126.             if (eq)
  127.             {
  128.                 if (ai->ai_type != ARG_SWITCH)
  129.                     eq = (cmp_arg[strlen(nxt_arg)] == '=');
  130.             }
  131. #endif
  132.             lastch = cmp_arg[strlen(nxt_arg)];
  133.             eq &= (lastch == '\0') || (lastch == '=');
  134.  
  135.             nxt_arg = strtok(NULL, "=");
  136.         }                       /* while */
  137.  
  138.     }
  139.     else
  140.     {
  141.         eq = FALSE;
  142.     }
  143.  
  144.     ufreestr(lst_arg);
  145.  
  146.     return eq;
  147. }
  148.  
  149. /*
  150.  * clr_ai_set
  151.  *
  152.  * clear all ai_set bits in all _arginfo entries of an _arglist
  153.  *
  154.  */
  155. static VOID clr_ai_set(ARGLIST * al)
  156. {
  157. #if 0
  158.     struct dlnode *nd;
  159.     struct arginfo *ai;
  160.  
  161.     if (al)
  162.         if (al->al_list)
  163.             if (nd = al->al_list->first)
  164.                 while (nd)
  165.                 {
  166.  
  167.                     if (ai = (struct arginfo *) nd->data)
  168.                         ai->ai_set = FALSE;
  169.                     nd = nd->next;
  170.  
  171.                 }
  172. #endif
  173.     if (al && (al->al_list))
  174.     {
  175.         struct dlnode *nd = al->al_list->first;
  176.  
  177.         while (nd)
  178.         {
  179.             struct arginfo *ai = (struct arginfo *) nd->data;
  180.  
  181.             if (ai)
  182.                 ai->ai_set = FALSE;
  183.             nd = nd->next;
  184.         }
  185.     }
  186. }
  187.  
  188. /*
  189.  * reset_nokeywd
  190.  *
  191.  * set al_nokeywd to first entry w/o ARG_KEYWORD flag
  192.  *
  193.  */
  194. static VOID reset_nokeywd(ARGLIST * al)
  195. {
  196.     /*
  197.      * NOTE: _al must be fully initialised _arglist,
  198.      *       otherwise _set_args() would have rejeceted
  199.      *       it. therefor no "al == NULL" check is done
  200.      *       when setting _nd and _ai.
  201.      */
  202.     struct dlnode *nd = al->al_list->first;
  203.     struct arginfo *ai = (struct arginfo *) nd->data;
  204.  
  205.     if (ai->ai_flags & ARG_KEYWORD || (ai->ai_type == ARG_SWITCH))
  206.     {
  207.         al->al_nokeywd = NULL;
  208.  
  209.         do
  210.         {
  211.             if ((ai->ai_flags & ARG_KEYWORD)
  212.                 || (ai->ai_type == ARG_SWITCH))
  213.             {
  214.                 nd = nd->next;
  215.                 if (nd)
  216.                     ai = (struct arginfo *) nd->data;
  217.             }
  218.             else
  219.                 al->al_nokeywd = ai;
  220.         }
  221.         while (nd && !(al->al_nokeywd));
  222.     }
  223.     else
  224.     {
  225.         al->al_nokeywd = ai;
  226.     }
  227. }
  228.  
  229. /*
  230.  * find_nxt_nokeywd
  231.  *
  232.  * find next entry w/o ARG_KEYWORD flag set
  233.  *
  234.  */
  235. static VOID find_nxt_nokeywd(ARGLIST * al)
  236. {
  237.     if (al->al_nokeywd)
  238.     {
  239. #if 0
  240.         /*
  241.          * find entry in al_list pointing to al_nokeywd
  242.          */
  243.         struct dlnode *nd = al->al_list->first;
  244.         struct arginfo *ai;
  245.  
  246.         while (al->al_nokeywd != (struct arginfo *) nd->data)
  247.             nd = nd->next;
  248.  
  249.         /*
  250.          * find next entry in al_list w/o ARG_KEYWORD
  251.          */
  252.         nd = nd->next;
  253.         al->al_nokeywd = NULL;
  254.         while (nd && (al->al_nokeywd == NULL))
  255.         {
  256.             ai = (struct arginfo *) nd->data;
  257.  
  258.             if ((ai->ai_flags & ARG_KEYWORD)
  259.                 || (ai->ai_type == ARG_SWITCH)
  260.                 )
  261.                 nd = nd->next;
  262.             else
  263.                 al->al_nokeywd = ai;
  264.         };
  265. #endif
  266.         /*
  267.          * find entry in al_list pointing to al_nokeywd
  268.          */
  269.         struct dlnode *nd = al->al_list->first;
  270.         struct arginfo *ai;
  271.  
  272.         /*
  273.          * find next entry in al_list w/o ARG_KEYWORD
  274.          */
  275.         al->al_nokeywd = NULL;
  276.         while (nd && (al->al_nokeywd == NULL))
  277.         {
  278.             BOOL is_keywd = FALSE;
  279.             BOOL multiple_nokeywd = FALSE;
  280.  
  281.             ai = (struct arginfo *) nd->data;
  282.  
  283.             is_keywd = ai->ai_flags & ARG_KEYWORD;
  284.             multiple_nokeywd =
  285.                 (ai->ai_flags & ARG_MULTIPLE)
  286.                 && !is_keywd;
  287.  
  288.             if (((ai->ai_flags & ARG_KEYWORD)
  289.                  || (ai->ai_type == ARG_SWITCH)
  290.                  || (ai->ai_set))
  291.                 && !multiple_nokeywd)
  292.             {
  293.                 nd = nd->next;
  294.             }
  295.             else
  296.             {
  297.                 al->al_nokeywd = ai;
  298.             }
  299.         }
  300.     }
  301. }
  302.  
  303. /*
  304.  *
  305.  * error functions for _set_args()
  306.  *
  307.  */
  308. static VOID set_argerr(int num, STRPTR arg)
  309. {
  310.     if (no_argerr)
  311.     {
  312.         no_argerr = FALSE;
  313.         any_argerr = TRUE;
  314.  
  315.         arg_error_num = num;
  316.         arg_error_arg = arg;
  317.     }
  318. }
  319.  
  320. static VOID clr_argerr(VOID)
  321. {
  322.     no_argerr = TRUE;
  323.     any_argerr = FALSE;
  324.     arg_error_num = 0;
  325.     arg_error_arg = NULL;
  326. }
  327.  
  328. /*
  329.  * strargerr
  330.  *
  331.  * returns string containing detailed error message of
  332.  * error occured in last call of _set_args()
  333.  *
  334.  */
  335. STRPTR strargerr(VOID)
  336. {
  337.     STRPTR str = "unknown error";
  338.  
  339.     switch (arg_error_num)
  340.     {
  341.     case ASE_NO_MEM:
  342.         str = "out of memory";
  343.         break;
  344.  
  345.     case ASE_OCCURED_TWICE:
  346.         str = "argument occured twice";
  347.         break;
  348.  
  349.     case ASE_UNKNOWN_KEYWORD:
  350.         str = "unknown keyword";
  351.         break;
  352.  
  353.     case ASE_INVALID_NUM:
  354.         str = "invalid numeric argument";
  355.         break;
  356.  
  357.     case ASE_INVALID_ENUM:
  358.         str = "invalid enumerator value";
  359.         break;
  360.  
  361.     case ASE_REQUIRED_MISS:
  362.         str = "required argument missing";
  363.         break;
  364.  
  365.     case ASE_EMPTY_TEMPLATE:
  366.         str = "empty template";
  367.         break;
  368.  
  369.     case ASE_OUT_OF_RANGE:
  370.         str = "numeric argument out of range";
  371.         break;
  372.     case ASE_NO_VAL_AFTER_KW:
  373.         str = "value after keyword missing";
  374.         break;
  375.  
  376.     case ASE_HANDLE_FUNC:       /* error in handle function */
  377.         str = arg_error_hfs;
  378.         break;
  379.     }                           /* switch */
  380.  
  381.     strcpy(argerrstr, str);
  382.     if (arg_error_arg)
  383.     {
  384.         strncat(argerrstr, ": ", SIZE_ARGERRSTR - strlen(str) - 1);
  385.         strncat(argerrstr, arg_error_arg, SIZE_ARGERRSTR - strlen(str) - 3);
  386.     }
  387.  
  388.     if (arg_error_num)
  389.     {
  390.         return argerrstr;
  391.     }
  392.     else
  393.     {
  394.         return NULL;
  395.     }
  396. }
  397.  
  398. /*
  399.  * pargerr
  400.  *
  401.  * printf error message from last call of _set_args()
  402.  *
  403.  */
  404. VOID pargerr(VOID)
  405. {
  406.     if (arg_error_num)
  407.     {
  408.         fprintf(stderr, "%s\n", strargerr());
  409.     }
  410. }
  411.  
  412. /*
  413.  * set_arg_value
  414.  *
  415.  * sets argument _ai->ai_dest with value specified in _arg
  416.  *
  417.  */
  418. static UBYTE set_arg_value(struct arginfo *ai, STRPTR arg, STRPTR arg2, BOOL keywd)
  419. {
  420.     APTR dest = ai->ai_dest;
  421.     STRPTR param;
  422.     UBYTE arg_incr = 0;         /* set to 1 if arg2 is used */
  423.     BOOL arg2used = FALSE;
  424.  
  425.     /* evaluate parameter:                                 */
  426.     /*   if arg is equal to arg-id of ai (no other chars   */
  427.     /*   following), the param is taken from the next arg. */
  428.     /*   otherwise, the arg is scanned for '=' and the     */
  429.     /*   rest of the arg is taken as param                 */
  430.     if (keywd && !(ai->ai_type == ARG_SWITCH))
  431.     {
  432.         param = arg;
  433.         while (param[0] && (param[0] != '='))
  434.             param++;
  435.         if (param[0])
  436.             param++;
  437.         else
  438.         {
  439.             param = arg2;
  440.             arg2used = TRUE;
  441.             if (!param)
  442.                 set_argerr(ASE_REQUIRED_MISS, arg);
  443.         }
  444.     }
  445.     else
  446.         param = arg;
  447.  
  448.     /*
  449.      * set switch/arg-value
  450.      */
  451.     if (no_argerr)
  452.     {
  453.         if (ai->ai_func)
  454.         {
  455.             /* call handle function with arg value */
  456.             arg_error_hfs = (*(ai->ai_func)) (param);
  457.             if (arg_error_hfs)
  458.                 set_argerr(ASE_HANDLE_FUNC, param);
  459.         }
  460.         else if (ai->ai_type == ARG_SWITCH)     /* switch */
  461.         {
  462.             *((BOOL *) dest) = TRUE;
  463.         }
  464.         else
  465.         {
  466.             /*
  467.              * check if argument already set by this set_args()
  468.              */
  469.             if ((ai->ai_set == AIS_SET_LOCAL)
  470.                 && !((ai->ai_flags & ARG_OVERWRITE)
  471.                      || (ai->ai_flags & ARG_MULTIPLE)))
  472.             {
  473.                 set_argerr(ASE_OCCURED_TWICE, arg);
  474.             }
  475.             else
  476.             {
  477.                 ai->ai_set = AIS_SET_LOCAL;
  478.             }
  479.  
  480.             if (no_argerr)
  481.             {
  482.                 APTR aparam = NULL;
  483.                 DLLIST **dest_list = (DLLIST **) dest;
  484.                 LONG along;
  485.  
  486.                 /*
  487.                  * get new value and  store it in aparam
  488.                  */
  489.                 if (!param)
  490.                 {
  491.                     /* missing param */
  492.                     set_argerr(ASE_NO_VAL_AFTER_KW, arg);
  493.                 }
  494.                 if (ai->ai_type == ARG_TEXT)
  495.                 {               /* text */
  496.                     aparam = (APTR) param;
  497.                 }
  498.                 else if (ai->ai_type == ARG_LONG)
  499.                 {               /* long */
  500.                     if (!str2long(param, &along))
  501.                         set_argerr(ASE_INVALID_NUM, arg);
  502.                     else
  503.                         aparam = (APTR) along;  /* what a pervert! */
  504.                 }
  505.                 else if (ai->ai_type == ARG_ENUM)
  506.                 {
  507.                     LONG aenum = strenum(param, ai->ai_misc1.ai_enum,
  508.                                          '|', STEN_NOCASE);
  509.  
  510.                     if (!aenum)
  511.                         set_argerr(ASE_INVALID_ENUM, arg);
  512.                     else
  513.                         aparam = (APTR) aenum;  /* what a pervert! */
  514.                 }
  515. #if 0
  516.                 if (!param)     /* missing param */
  517.                     set_argerr(ASE_NO_VAL_AFTER_KW, arg);
  518.                 if (ai->ai_type == ARG_TEXT)    /* text */
  519.                     *((STRPTR *) dest) = param;
  520.                 else if (ai->ai_type == ARG_LONG)
  521.                 {               /* long */
  522.                     if (!str2long(param, (LONG *) dest))
  523.                         set_argerr(ASE_INVALID_NUM, arg);
  524.                 }
  525. #endif
  526.  
  527.                 /*
  528.                  * set new value
  529.                  */
  530.                 if (no_argerr)
  531.                 {
  532.                     if (ai->ai_flags & ARG_MULTIPLE)
  533.                     {
  534.                         if (!(*dest_list))
  535.                             *dest_list = init_dllist(NULL);
  536.                         if (*dest_list)
  537.                         {
  538.                             if (!app_dlnode(*dest_list, aparam))
  539.                                 set_argerr(APE_NO_MEM, arg);
  540.                         }
  541.                         else
  542.                             set_argerr(APE_NO_MEM, arg);
  543.                     }
  544.                     else
  545.                     {
  546.                         if (ai->ai_type == ARG_LONG)
  547.                             *((LONG *) dest) = (LONG) aparam;
  548.                         else if (ai->ai_type == ARG_ENUM)
  549.                             *((LONG *) dest) = (LONG) aparam;
  550.                         else if (ai->ai_type == ARG_TEXT)
  551.                             *((STRPTR *) dest) = (STRPTR) aparam;
  552.  
  553.                     }
  554.                 }
  555.             }
  556.         }
  557.  
  558.         if (arg2used)           /* set return value that arg2 */
  559.             arg_incr = 1;       /* is skipped outside this func */
  560.     }
  561.  
  562.     return (arg_incr);
  563. }
  564.  
  565. /*
  566.  * check_required_set
  567.  *
  568.  * check, if all required arguments are set
  569.  *
  570.  */
  571. static VOID check_required_set(ARGLIST * al)
  572. {
  573.     DLNODE *nd = al->al_list->first;
  574.     ARGINFO *ai;
  575.  
  576.     do
  577.     {
  578.         ai = (struct arginfo *) dln_data(nd);
  579.  
  580.         if ((ai->ai_flags & ARG_REQUIRED) && (ai->ai_set == AIS_UNSET))
  581.             set_argerr(ASE_REQUIRED_MISS, ai->ai_id);
  582.         else
  583.             nd = dln_next(nd);
  584.     }
  585.     while (nd && no_argerr);
  586. }
  587.  
  588. /*
  589.  * set_args_file
  590.  *
  591.  * set args from argument file
  592.  */
  593. ARGFILE *new_argfile(char *argfname)
  594. {
  595. #define SIZE_FGETSBUF 1024
  596.     ARGFILE *argf = umalloc(sizeof(ARGFILE));
  597.  
  598.     BOOL no_argerr = TRUE;
  599.     if (argf)
  600.     {
  601.         FILE *file = NULL;
  602.  
  603.         argf->argc = 0;
  604.         argf->argv = umalloc(2 * sizeof(char *));
  605.         argf->argv[0] = NULL;
  606.         argf->argv[1] = NULL;
  607.  
  608.         if (argfname)
  609.         {
  610.             argf->argv[0] = strclone(argfname);
  611.             file = fopen(argfname, "r");
  612.         }
  613.         if (file)
  614.         {
  615.             STRPTR fgetsbuf = umalloc(SIZE_FGETSBUF);   /* alloc buf for fgets() */
  616.  
  617.             if (fgetsbuf)
  618.             {
  619.                 STRPTR argline = NULL;
  620.                 no_argerr = FALSE;
  621.  
  622.                 do
  623.                 {
  624.                     argline = fgets(fgetsbuf, SIZE_FGETSBUF, file);
  625.                     if (argline)
  626.                     {
  627.                         int i = 0;      /* loop var */
  628.  
  629.                         /* increse argv-array */
  630.                         char **old_argv = argf->argv;
  631.                         argf->argc++;
  632.                         argf->argv = umalloc((argf->argc + 2) * sizeof(char *));
  633.  
  634.                         /* copy old argv-array */
  635.                         for (i = 0; i <= (argf->argc); i++)
  636.                         {
  637.                             argf->argv[i] = old_argv[i];
  638.                         }
  639.  
  640.                         /* free old argv-array */
  641.                         ufree(old_argv);
  642.  
  643.                         /* strip succeeding linefeed */
  644.                         while (fgetsbuf[0]
  645.                                && strchr("\r\n", fgetsbuf[strlen(fgetsbuf) - 1]))
  646.                         {
  647.                             fgetsbuf[strlen(fgetsbuf) - 1] = '\0';
  648.                         }
  649.  
  650.                         /* assign new argv */
  651.                         argf->argv[argf->argc] = strclone(fgetsbuf);
  652.                         argf->argv[argf->argc + 1] = NULL;
  653.                     }
  654.                 }
  655.                 while (argline);
  656.                 argf->argc++;
  657.             }
  658.  
  659.             ufree(fgetsbuf);    /* cleanup resources */
  660.             fclose(file);
  661.         }
  662.     }
  663.  
  664.     return (argf);
  665. }
  666.  
  667. ARGFILE *new_argfilev(STRPTR fname[])
  668. {
  669.     int i=0;
  670.  
  671.     while(fname[i] && !fexists(fname[i]))
  672.     {
  673.         i++;
  674.     }
  675.  
  676.     return(new_argfile(fname[i]));
  677. }
  678.  
  679. /*
  680.  * del_argfile: release all resources allocated by new_argfile
  681.  */
  682. VOID del_argfile(ARGFILE * argf)
  683. {
  684.     if (argf)
  685.     {
  686.         while (argf->argc+1)
  687.         {
  688.             ufreestr(argf->argv[argf->argc]);
  689.             argf->argc--;
  690.         }
  691.         ufree(argf->argv);
  692.         ufree(argf);
  693.     }
  694. }
  695.  
  696. /*
  697.  * set_args_argv
  698.  *
  699.  * check and set arguments according to template specified in _al
  700.  *
  701.  * params: argc, argv[]...arguments from _main
  702.  *         al.............argument template (result from _prepare_args())
  703.  * result: TRUE, if no error occured
  704.  * errors: return FALSE, error information in _arg_error_???
  705.  *
  706.  */
  707. BOOL set_args_argv(int argc, char *argv[], ARGLIST * al)
  708. {
  709. #if 0
  710.     DA(fprintf(stderr, DUA "set_args()\n"));
  711. #endif
  712.     clr_argerr();
  713.     clr_ai_set(al);
  714.     reset_nokeywd(al);
  715.  
  716.     argidx = 1;
  717.  
  718.     if (al == NULL)
  719.         set_argerr(ASE_EMPTY_TEMPLATE, argv[argidx]);
  720.     else if (al->al_list == NULL)
  721.         set_argerr(ASE_EMPTY_TEMPLATE, argv[argidx]);
  722.  
  723.     while ((argidx < argc) && no_argerr)
  724.     {
  725.         struct arginfo search_ai;
  726.         struct arginfo *found_ai;
  727.         struct dlnode *ainode;
  728.         STRPTR arg2 = NULL;     /* passed to set_arg_value */
  729. #if 0                           /* TODO:remove */
  730.         STRARR sas_c_is_buggy[20];
  731. #endif
  732.  
  733.         /*
  734.          * search for entry in arginfo-list
  735.          */
  736.         search_ai.ai_id = argv[argidx];
  737.         ainode = find_dlnode(al->al_list->first, &search_ai, compare_arginfo);
  738.  
  739.         /* evaluate next argument (passed to set_arg_value) */
  740.         /* TODO: check if "<" or "<=" */
  741.         if (argidx < argc - 1)
  742.             arg2 = argv[argidx + 1];
  743.  
  744.         DA(fprintf(stderr, DUA "  arg: `%s'\n", argv[argidx]));
  745.  
  746. #if 0                           /* TODO:remove */
  747.         /* this line compensates a bug in sas/c 6.51 optimizer */
  748.         strncpy(sas_c_is_buggy, argv[argidx], 20);
  749. #endif
  750.  
  751.         if (ainode)
  752.         {
  753.             found_ai = (struct arginfo *) ainode->data;
  754.             argidx += set_arg_value(found_ai, argv[argidx], arg2, TRUE);
  755.         }
  756.         else
  757.         {
  758.             find_nxt_nokeywd(al);
  759.             if (al->al_nokeywd)
  760.             {
  761.                 argidx += set_arg_value(al->al_nokeywd, argv[argidx], arg2, FALSE);
  762.             }
  763.             else
  764.             {
  765.                 set_argerr(ASE_UNKNOWN_KEYWORD, argv[argidx]);
  766. #if 0
  767.                 DA(fprintf(stderr, DUA "  unknown keyword\n"));
  768. #endif
  769.             }
  770.         }
  771.  
  772.         argidx++;
  773.     }                           /* while */
  774.  
  775.     /* mark all arguments that have been set locally
  776.      * (with ai_set==AIS_SET_LOCAL) as set */
  777.     if (no_argerr)
  778.     {
  779.         DLNODE *nd = dll_first(al->al_list);
  780.         while (nd)
  781.         {
  782.             ARGINFO *ai = (struct arginfo *) dln_data(nd);
  783.             if (ai->ai_set == AIS_SET_LOCAL)
  784.                 ai->ai_set = AIS_SET_PREVIOUS;
  785.             nd = dln_next(nd);
  786.         }
  787.     }
  788.  
  789.     return no_argerr;
  790. }
  791.  
  792. /*
  793.  * check_args
  794.  *
  795.  * check for required args missing
  796.  */
  797. BOOL check_args(ARGLIST * al)
  798. {
  799.     /* check, if all required arguments were set */
  800.     if (no_argerr)
  801.     {
  802.         check_required_set(al);
  803.     }
  804.  
  805.     return no_argerr;
  806. }
  807.  
  808. /*
  809.  * set_args
  810.  *
  811.  * set and check args from arg-vector
  812.  */
  813. BOOL set_args(int argc, char *argv[], ARGLIST * al)
  814. {
  815.     return( (BOOL)(set_args_argv(argc,argv,al) && check_args(al)));
  816. }
  817.  
  818. /*
  819.  * set_args_file
  820.  *
  821.  * set args read from file
  822.  */
  823. BOOL set_args_file(ARGFILE *argf, ARGLIST *argl)
  824. {
  825.     return(set_args((argf)->argc, (argf)->argv, argl));
  826. }
  827.  
  828.  
  829.